home *** CD-ROM | disk | FTP | other *** search
- /* Easy Sound */
-
- /// "includes"
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <devices/audio.h>
- #include <stdio.h>
- #include "EasySound.h"
-
- #define CLOCK_CONSTANT 3579545
-
- /* An IOAudio pointer to each sound channel: */
- struct IOAudio *IOA[4] = {
- NULL, NULL, NULL, NULL
- };
-
- typedef LONG Fixed;
- typedef struct {
- ULONG oneShotHiSamples; /* #samples in the high octave 1-shot part */
- ULONG repeatHiSamples; /* #samples in the high octave repeat part */
- ULONG samplesPerHiCycle; /* #samples/cycle in high octave, else 0 */
- UWORD samplesPerSec; /* Data sampling rate */
- UBYTE ctOctave; /* Number of octaves of waveforms */
- UBYTE sCompression; /* Data compression technique used */
- Fixed volume; /* Playback volume from 0 to 0x10000 */
- } Voice8Header;
-
- /* Declare the functions we are going to use: */
-
- BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
- BYTE priority, WORD delta_rate, UWORD repeat,
- ULONG start, ULONG time, BOOL wait);
-
- void ESStopSound (UBYTE channel);
-
- BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
- BYTE priority, struct SoundInfo *info, ULONG start,
- ULONG time);
-
- void ESRemoveSound (struct SoundInfo *info);
-
- struct SoundInfo *ESPrepareSound (STRPTR file);
-
- UWORD ESLoadSound (STRPTR filename, struct SoundInfo *info);
-
- ULONG ESGetSize (STRPTR filename);
-
- ULONG ESSizeIFF (STRPTR filename);
-
- UWORD ESReadIFF (STRPTR filename, struct SoundInfo *info);
-
- BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr);
- ///
- /// "ESPlaySound"
- /* ESPlaySound() */
- /* ESPlaySound() plays one already prepared sound effect. You can decide */
- /* what volume, which channel, what rate, which priority, how many times */
- /* the sound should be played and so on... */
- /* */
- /* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start, */
- /* time, wait ); */
- /* */
- /* ok: (BOOL) If the sound was played successfully TRUE is */
- /* returned, else FALSE. */
- /* */
- /* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. This */
- /* pointer was returned by PrepareSound(). */
- /* */
- /* vol: (UWORD) Volume, 0 to 64. */
- /* */
- /* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* */
- /* pri: (BYTE) What priority should be used. See header file for a */
- /* complete list of recommended priorities. */
- /* */
- /* drate: (WORD) Delta rate. When the sound is prepared, the record */
- /* rate is automatically stored in the SoundInfo structure, */
- /* so if you do not want to change the rate, write NORMALRATE. */
- /* */
- /* times: (UWORD) How many times the sound should be played. If you */
- /* want to play the sound forever, write NONSTOP. (To stop a */
- /* sound call the function StopSound().) */
- /* */
- /* start: (ULONG) Where in the sound data we should start to play. (If */
- /* you want to start at the beginning of the sound data set start */
- /* to 0.) */
- /* */
- /* time: (ULONG) For how long time the sound should be played. If you */
- /* want to play all of the sound data set time to 0. */
- /* */
- /* wait: (BOOL) Set this parameter to WAIT if you want to wait for the */
- /* sound to be completed. If you set it to DO_NOT_WAIT, your */
- /* program will continue to run while the sound is played. */
- /* NOTE! Do not try to play a sound continiously (times set to */
- /* NONSTOP) and at the same time set this field to TRUE! The */
- /* request will then never be completed and your program will */
- /* come to a dead lock!! */
-
- BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
- BYTE priority, WORD delta_rate, UWORD times, ULONG start,
- ULONG time, BOOL wait) {
- /*
- * Before we may play the sound, we must make sure that the sound is not
- * already being played. We will therefore call the function
- * ISStopSound(), in order to stop the sound if it is playing:
- */
- ESStopSound (channel);
-
- if (ESPrepareIOA (CLOCK_CONSTANT/info->RecordRate + delta_rate, volume, times, channel, priority, info, start, time)) {
-
- BeginIO (IOA[channel]);
- if (wait)
- WaitIO (IOA[channel]);
-
- return (TRUE); /* OK! */
- }
- else
- return (FALSE); /* ERROR! */
- }
- ///
- /// "ESStopSound"
- /* ESStopSound() */
- /* ESStopSound() will stop the specified audio channel from continuing */
- /* to play the sound. It will also close all devices and ports that */
- /* have been opened, and deallocate some memory that have been */
- /* allocated. */
- /* */
- /* Synopsis: ISStopSound( channel ); */
- /* channel: (UBYTE) The audio channel that should be stopped. (LEFT0, */
- /* LEFT1, RIGHT0 or RIGHT1.) */
-
- void ESStopSound (UBYTE channel)
- {
- /* Check if the IOAudio structure exist: */
- if (IOA[channel]) {
- /* 1. Stop the sound: */
- AbortIO (IOA[channel]);
-
- /* 2. If there exist a Sound Device, close it: */
- if (IOA[channel]->ioa_Request.io_Device)
- CloseDevice (IOA[channel]);
-
- /* 3. If there exist a Message Port, delete it: */
- if (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort)
- DeletePort (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort);
-
- /* 4. Remove the request block: */
- DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
-
- /* 5. Set the pointer to NULL so we know that this */
- /* request has now been deleted: */
- IOA[channel] = NULL;
- }
- }
-
- ///
- /// "ESPrepareIOA"
- /* ESPrepareIOA() */
- /* ESPrepareIOA() allocates and initializes an IOAudio structure. */
- /* */
- /* Synopsis: ok = ISPrepareIOA( per, vol, cyc, cha, ptr, start, time ); */
- /* */
- /* ok: (BOOL) If the IOAudio structure was allocated and */
- /* initialized successfully, TRUE is returned, else FALSE. */
- /* per: (UWORD) Period time. */
- /* vol: (UWORD) Volume, 0 to 64. */
- /* cyc: (UWORD) How many times the sound should be played. */
- /* (0 : forever) */
- /* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. */
- /* start: (ULONG) Where in the sound data we should start to play. */
- /* time: (ULONG) For how long time the sound should be played. */
-
- BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
- BYTE priority, struct SoundInfo *info, ULONG start,
- ULONG time)
- {
- /* Store error numbers here: */
- BYTE error;
-
- /* Declare a pointer to a MsgPort structure: */
- struct MsgPort *port;
-
- /* Get a reply port: (No name, normal priority) */
- port = (struct MsgPort *)
- CreatePort (NULL, 0);
-
- /* Did we get a reply port? */
- if (!port) {
- /* Bad news! We did not get a reply port. */
-
- /* Return with an error value: */
- return (FALSE);
- }
-
- /* Create an IOAudio request: */
- IOA[channel] = (struct IOAudio *)
- CreateExtIO (port, sizeof (struct IOAudio));
-
- /* Could we allocate enough memory? */
- if (!IOA[channel]) {
- /* Tough luck! We did not get a request block. */
-
- /* Close the reply port: */
- DeletePort (port);
-
- /* Return with an error value: */
- return (FALSE);
- }
-
- /* Initialize the IOAudion structure: */
-
- /* Set priority: */
- IOA[channel]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
-
- /* Set channel: (This program tries to reserve one specific */
- /* audio channel. It does not support an allocation array */
- /* with several options.) */
- info->channel_bit = 1 << channel;
-
- /* Give the request block a pointer to our simple allocation array: */
- IOA[channel]->ioa_Data = &(info->channel_bit);
-
- /* Set the length of our allocation array: */
- IOA[channel]->ioa_Length = sizeof (UBYTE);
-
- /* Open Audio Device: */
- error = OpenDevice (AUDIONAME, 0, IOA[channel], 0);
-
- /* Have wee successfully opened it? */
- if (error) {
- /* Hard times! Could not open the device! */
-
- /* Delete the request block: */
- DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
-
- /* Close the reply port: */
- DeletePort (port);
-
- /* Set audio pointer to NULL so we know that */
- /* we do not have any request block here: */
- IOA[channel] = NULL;
-
- /* Return with an error value: */
- return (FALSE); /* ERROR! */
- }
-
- /* We now have a reply port, a request block, one */
- /* audio channel reserved and the audio device has */
- /* been opened. Prepare to play: */
-
- /* Initialize the request block with the users requirements: */
- IOA[channel]->ioa_Request.io_Flags = ADIOF_PERVOL;
-
- /* We want to play sound (write data to the audio device): */
- IOA[channel]->ioa_Request.io_Command = CMD_WRITE;
-
- /* Set period value: */
- IOA[channel]->ioa_Period = period;
-
- /* Set volume: */
- IOA[channel]->ioa_Volume = volume;
-
- /* Number of times the sound wave should be played: */
- IOA[channel]->ioa_Cycles = cycles;
-
- /* If the user has specified a play time we use */
- /* it, else we play the complete sound: */
- if (time)
- IOA[channel]->ioa_Length = time;
- else
- IOA[channel]->ioa_Length = info->FileLength;
-
- /* Set start position in the waveform: */
- IOA[channel]->ioa_Data = info->SoundBuffer + start;
-
- /* Everything has been prepared, return with OK: */
- return (TRUE);
- }
- ///
- /// "ESRemoveSound"
- /* ESRemoveSound() */
- /* ESRemoveSound() will stop playing the sound, and deallocate all memory */
- /* that was allocated by the PrepareSound() function. Before your program */
- /* terminates, all soundeffects that have been prepared, MUST be removed. */
- /* */
- /* IMPORTANT! Each channel that is currently playing the sound must be */
- /* stopped before you may remove the sound!!!! (Use the ESStopSound() */
- /* function.) */
- /* */
- /* Synopsis: ESRemoveSound( pointer ); */
- /* */
- /* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
-
- void ESRemoveSound (struct SoundInfo *info)
- {
- /* IMPORTANT! The sound must have been */
- /* stopped before you may remove it!!! */
-
- /* Have we allocated a SoundInfo structure? */
- if (info) {
- /* Deallocate the sound buffer: */
- FreeMem (info->SoundBuffer, info->FileLength);
-
- /* Deallocate the SoundInfo structure: */
- FreeMem (info, sizeof (struct SoundInfo));
- info = NULL;
- }
- }
-
- ///
- /// "ESPrepareSound"
- /* ESPrepareSound()
-
- ESPrepareSound() loads a sampled sound file (IFF or FutureSound) into a
- buffer that is automatically allocated. All information about the sound
- (record rate, length, buffersize etc) is put into an SoundInfo structure.
- If ESPrepareSound() has successfully prepared the sound it returns a
- pointer to a SoundInfo structure, otherwise it returns NULL.
-
- Synopsis: pointer = ESPrepareSound( filename );
-
- pointer: (struct SoundInfo *) Pointer to a SoundInfo structure.
-
- filename: (STRPTR) Pointer to a string containing the name of the
- sound file. For example "df0:Explosion.snd".
- */
-
- struct SoundInfo *ESPrepareSound (STRPTR file) {
-
- struct SoundInfo *info;
-
- /*
- * Allocate memory for a SoundInfo structure: (The memory can be of
- * any type, and should be cleared.)
- */
- info = (struct SoundInfo *)AllocMem (sizeof (struct SoundInfo), MEMF_CLEAR);
- if (!info) {
- return (NULL);
- }
-
- /*
- * Get the size of the sound file, and store it in the SoundInfo
- * structure:
- */
- info->FileLength = ESGetSize (file);
- if (info->FileLength == 0) {
- FreeMem (info, sizeof (struct SoundInfo));
- return (NULL);
- }
-
- /*
- * Allocate enough memory for the sampled sound, and store a pointer to
- * the buffer in the SoundInfo structure: (Remember that sound data must
- * be in chip memory.)
- */
- info->SoundBuffer = (BYTE *) AllocMem (info->FileLength, MEMF_CHIP | MEMF_CLEAR);
- if (!info->SoundBuffer) {
- FreeMem (info, sizeof (struct SoundInfo));
- return (NULL);
- }
-
- info->RecordRate = ESLoadSound (file, info);
- if (info->RecordRate == 0) {
- FreeMem (info->SoundBuffer, info->FileLength);
- FreeMem (info, sizeof (struct SoundInfo));
- return (NULL);
- }
-
- /*
- * The sound has now successfully been loaded!
- */
-
- /*
- * Old FutureSound files were saved in kHz. If the record rate is less
- * than one hundered, we know it is an old FutureSound file, and simply
- * multiply the rate with one thousand:
- */
- if (info->RecordRate < 100)
- info->RecordRate *= 1000;
-
- /* Return a pointer to the SoundInfo structure: */
- return (info);
- }
- ///
- /// "ESLoadSound"
- /* ESLoadSound() */
- /* ESLoadSound() will load sampled sound that was either saved in IFF */
- /* or FutureSound format. */
- /* */
- /* Synopsis: rate = ESLoadSound( filename, pointer ); */
- /* */
- /* rate: (UWORD) The record rate is returned if the sound was */
- /* successfully loaded, else 0. */
- /* */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
- /* */
- /* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
-
- UWORD ESLoadSound (STRPTR filename, struct SoundInfo * info)
- {
- FILE *file_ptr; /* Pointer to a file. */
- ULONG length; /* Data Length. */
- UWORD record_rate; /* Record rate. */
-
- /* Check if it is an IFF File: */
- if (ESSizeIFF (filename)) {
- /* Yes, it is an IFF file. Read it: */
- return (ESReadIFF (filename, info));
- }
- else {
- /* No, then it is probably a FutureSound file. */
- /* Open the file so we can read it: */
- if ((file_ptr = fopen (filename, "r")) == 0)
- return (0); /* ERROR! Could not open the file! */
-
- /* Read the data length: */
- if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
- /* ERROR! Could not read the data length! */
- /* Close the file, and return zero: */
- fclose (file_ptr);
- return (0);
- }
-
- /* Read the record rate: */
- if (fread ((char *) &record_rate, sizeof (UWORD), 1, file_ptr) == 0) {
- /* ERROR! Could not read the record rate! */
- /* Close the file, and return zero: */
- fclose (file_ptr);
- return (0);
- }
-
- /* Read the sampled sound data into the buffer: */
- if (fread ((char *) info->SoundBuffer, length, 1, file_ptr) == 0) {
- /* ERROR! Could not read the data! */
- /* Close the file, and return zero: */
- fclose (file_ptr);
- return (0);
- }
-
- /* Close the file: */
- fclose (file_ptr);
-
- /* Return the record rate: */
- return (record_rate);
- }
- }
- ///
- /// "ESGetSize"
- /* ESGetSize() */
- /* ESGetSize() returns the size of the file which was saved in either */
- /* IFF or FutureSound format. */
- /* */
- /* Synopsis: length = ESGetSize( filename ); */
- /* */
- /* length: (ULONG) Data length. */
- /* */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
-
- ULONG ESGetSize (STRPTR filename)
- {
- FILE *file_ptr; /* Pointer to a file. */
- ULONG length; /* Data length. */
-
- /* Check if it is an IFF File: */
- if ((length = ESSizeIFF (filename)) == 0) {
- /* No, then it is probably a FutureSound file. */
- /* Open the file so we can read it: */
- if ((file_ptr = fopen (filename, "r")) == 0)
- return (0); /* ERROR! Could not open the file! */
-
- /* Read the data length: */
- if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
- /* ERROR! Could not read the data length! */
- /* Close the file, and return zero: */
- fclose (file_ptr);
- return (0);
- }
-
- /* Close the file: */
- fclose (file_ptr);
- }
- return (length);
- }
- ///
- /// "ESSizeIFF"
- /* ESSizeIFF() */
- /* ESSizeIFF() returns the size of an IFF file, or zero if something */
- /* went wrong (for example, It was not an IFF file). */
- /* */
- /* Synopsis: length = ESSizeIFF( filename ); */
- /* */
- /* length: (ULONG) Data length. */
- /* */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* IFF file. For example "df0:Explosion.snd". */
-
- ULONG ESSizeIFF (STRPTR filename)
- {
- FILE *file_ptr; /* Pointer to a file. */
- STRPTR empty_string = " "; /* Four spaces. */
- LONG dummy; /* A dummy variable. */
- Voice8Header Header; /* Voice8Header structure. */
-
- /* Try to open the file: */
- if (file_ptr = fopen (filename, "r")) {
- fread ((char *) empty_string, 4, 1, file_ptr);
- if (strcmp (empty_string, "FORM") == 0) {
- /* Read twice: */
- fread ((char *) empty_string, 4, 1, file_ptr);
- fread ((char *) empty_string, 4, 1, file_ptr);
-
- /* Check if it is a "8SVX" file, or not: */
- if (strcmp (empty_string, "8SVX") == 0) {
- ESMoveTo ("VHDR", file_ptr);
- fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
- fread ((char *) &Header, sizeof (Header), 1, file_ptr);
-
- /* Close the file, and return the length: */
- fclose (file_ptr);
- return (Header.oneShotHiSamples + Header.repeatHiSamples);
- }
- }
- /* Close the file: */
- fclose (file_ptr);
- }
- /* Return zero: (ERROR) */
- return (0);
- }
- ///
- /// "ESReadIFF"
- /* ESReadIFF() */
- /* ESReadIFF() reads an IFF file into the buffer, and returns the record */
- /* rate. */
- /* */
- /* Synopsis: rate = ESReadIFF( filename, pointer ); */
- /* */
- /* rate: (UWORD) The record rate is returned if the sound was */
- /* successfully loaded, else 0. */
- /* */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
- /* */
- /* pointer: (struct SoundInfo *) Pointer to a SoundInfo structure. */
-
- UWORD ESReadIFF (STRPTR filename, struct SoundInfo * info)
- {
- FILE *file_ptr; /* Pointer to a file. */
- STRPTR empty_string = " "; /* Four spaces. */
- LONG dummy; /* A dummy variable. */
- Voice8Header Header; /* Voice8Header structure. */
-
- /* Try to open the file: */
- if (file_ptr = fopen (filename, "r")) {
- fread ((char *) empty_string, 4, 1, file_ptr);
- if (strcmp (empty_string, "FORM") == 0) {
- /* Read twice: */
- fread ((char *) empty_string, 4, 1, file_ptr);
- fread ((char *) empty_string, 4, 1, file_ptr);
-
- /* Check if it is a "8SVX" file, or not: */
- if (strcmp (empty_string, "8SVX") == 0) {
- ESMoveTo ("VHDR", file_ptr);
- fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
- fread ((char *) &Header, sizeof (Header), 1, file_ptr);
-
- ESMoveTo ("BODY", file_ptr);
- fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
- fread ((char *) info->SoundBuffer, Header.oneShotHiSamples +
- Header.repeatHiSamples, 1, file_ptr);
-
- /* Close the file, and return the record rate: */
- fclose (file_ptr);
- return (Header.samplesPerSec);
- }
- }
- /* Close the file: */
- fclose (file_ptr);
- }
- /* Return zero: (ERROR) */
- return (0);
- }
- ///
- /// "ESMoveTo"
- /* ESMoveTo() */
- /* ESMoveTo() walks through an IFF file, and looks for chunks. */
- /* */
- /* Synopsis: ESMoveTo( chunk, file_ptr ); */
- /* */
- /* chunk: (STRPTR) The chunk we want to get to. */
- /* */
- /* file_ptr: (FILE *) Pointer to an already opened file. */
-
- BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr)
- {
- STRPTR empty_string = " "; /* Four spaces. */
- int skip, loop; /* How much data should be skiped. */
- LONG dummy; /* A dummy variable. */
-
- /* As long as we have not reached the EOF, continue: */
- while (!feof (file_ptr)) {
- fread ((char *) empty_string, 4, 1, file_ptr);
-
- /* Have we found the right chunk? */
- if (strcmp (check_string, empty_string) == 0)
- return (0); /* YES! Return nothing. */
-
- /* Move foreward: */
- fread ((char *) &skip, sizeof (LONG), 1, file_ptr);
- for (loop = 0; loop < skip; loop++)
- fread ((char *) &dummy, 1, 1, file_ptr);
- }
- }
-
- ///
-
-